using System;
using System.Reflection;
using System.Windows.Forms;

namespace Be.Timvw.Framework.Windows.Forms
{
    public partial class AssemblyTypePicker : UserControl
    {
        private Assembly selectedAssembly;
        private Type selectedType;

        public AssemblyTypePicker()
        {
            this.InitializeComponent();
        }

        public virtual Assembly SelectedAssembly
        {
            get { return this.selectedAssembly; }
            set
            {
                if(this.selectedAssembly != value)
                {
                    this.selectedAssembly = value;
                    if(value != null)
                    {
                        this.textBoxAssembly.Text = value.Location;
                        if(this.selectedType != null)
                        {
                            this.SelectedType = this.selectedAssembly.GetType(this.selectedType.FullName, false);
                        }
                        this.buttonTypePicker.Enabled = true;
                    }
                    else
                    {
                        this.textBoxAssembly.Text = string.Empty;
                        this.SelectedType = null;
                        this.buttonTypePicker.Enabled = false;
                    }
                }
            }
        }

        public virtual Type SelectedType
        {
            get { return this.selectedType; }
            set
            {
                if(this.selectedType != value)
                {
                    if(value != null)
                    {
                        this.selectedType = value;
                        this.textBoxType.Text = value.FullName;
                    }
                    else
                    {
                        this.selectedType = null;
                        this.textBoxType.Text = string.Empty;
                    }
                }
            }
        }

        public event EventHandler<ItemEventArgs<Type[]>> TypesFound;

        private void buttonAssemblyPicker_Click(object sender, EventArgs e)
        {
            using(OpenFileDialog fileDialog = new OpenFileDialog())
            {
                fileDialog.AutoUpgradeEnabled = true;
                fileDialog.CheckFileExists = true;
                fileDialog.CheckPathExists = true;
                fileDialog.DefaultExt = "dll";
                fileDialog.DereferenceLinks = true;
                fileDialog.Filter = "Assembly Files (*.dll;*.exe)|*.dll;*.exe";
                fileDialog.Multiselect = false;
                fileDialog.RestoreDirectory = true;
                fileDialog.SupportMultiDottedExtensions = true;
                fileDialog.ShowReadOnly = true;
                fileDialog.Title = "Select Assembly File";
                fileDialog.ValidateNames = true;
                if(fileDialog.ShowDialog() == DialogResult.OK)
                {
                    string assemblyFile = fileDialog.FileName;
                    try
                    {
                        this.SelectedAssembly = Assembly.LoadFrom(assemblyFile);
                    }
                    catch(Exception)
                    {
                        this.SelectedAssembly = null;
                    }
                }
            }
        }

        private void buttonTypePicker_Click(object sender, EventArgs e)
        {
            if(this.selectedAssembly != null)
            {
                using(TypeTreePicker picker = new TypeTreePicker())
                {
                    Type[] assemblyTypes = this.selectedAssembly.GetExportedTypes();
                    ItemEventArgs<Type[]> typesFoundEventArgs = new ItemEventArgs<Type[]>(assemblyTypes);
                    EventHelper.Raise(this.TypesFound, this, typesFoundEventArgs);
                    assemblyTypes = typesFoundEventArgs.Item;
                    picker.LoadTypes(assemblyTypes);
                    picker.SelectedType = this.selectedType;

                    if(picker.ShowDialog() == DialogResult.OK)
                    {
                        this.SelectedType = picker.SelectedType;
                    }
                }
            }
        }

        private void textBoxAssembly_TextChanged(object sender, EventArgs e)
        {
            try
            {
                this.SelectedAssembly = Assembly.LoadFrom(this.textBoxAssembly.Text);
            }
            catch(Exception)
            {
                this.SelectedAssembly = null;
            }
        }
    }
}